/*
 * I2C_HAL.c
 *
 *  Created on: 08.08.2011
 *      Author: margel
 */

#include <stdint.h>
#include <stdio.h>

#include "appdefs.h"
#include "platform_config.h"
#include "stm32f10x.h"
#include "hw_config.h"
#include "lib_dbg.h"
#include "I2C_HAL.h"

void DelayMicroSeconds( int ms )
{
int i;
	for( ; ms > 0; ms-- )
		for( i = 20000; i > 0; i-- )
			asm volatile ("nop");
}


//==============================================================================
void I2c_Init ()
//==============================================================================
{
  SDA_LOW();                // Set port as output for configuration
  SCL_LOW();                // Set port as output for configuration

  //SDA_CONF=LOW;           // Set SDA level as low for output mode
  //SCL_CONF=LOW;           // Set SCL level as low for output mode

  SDA_HIGH();               // I2C-bus idle mode SDA released (input)
  SCL_HIGH();               // I2C-bus idle mode SCL released (input)
}

//==============================================================================
void I2c_StartCondition ()
//==============================================================================
{
  SDA_HIGH();
  SCL_HIGH();
  SDA_LOW();
  DelayMicroSeconds(10);  // hold time start condition (t_HD;STA)
  SCL_LOW();
  DelayMicroSeconds(10);
}

//==============================================================================
void I2c_StopCondition ()
//==============================================================================
{
  SDA_LOW();
  SCL_LOW();
  SCL_HIGH();
  DelayMicroSeconds(10);  // set-up time stop condition (t_SU;STO)
  SDA_HIGH();
  DelayMicroSeconds(10);
}

//==============================================================================
uint8_t I2c_WriteByte (uint8_t txByte)
//==============================================================================
{
  uint8_t mask,error=0;
  for (mask=0x80; mask>0; mask>>=1)   //shift bit for masking (8 times)
  { if ((mask & txByte) == 0) SDA_LOW();//masking txByte, write bit to SDA-Line
    else SDA_HIGH();
    DelayMicroSeconds(1);             //data set-up time (t_SU;DAT)
    SCL_HIGH();                         //generate clock pulse on SCL
    DelayMicroSeconds(5);             //SCL high time (t_HIGH)
    SCL_LOW();
    DelayMicroSeconds(1);             //data hold time(t_HD;DAT)
  }
  SDA_HIGH();                           //release SDA-line
  SCL_HIGH();                           //clk #9 for ack
  DelayMicroSeconds(1);               //data set-up time (t_SU;DAT)
  if(GPIO_ReadInputDataBit( SHT21_GPIO_PORT, SHT21_GPIO_SDA_PIN ) == Bit_SET ) error=ACK_ERROR; //check ack from i2c slave
  SCL_LOW();
  DelayMicroSeconds(20);              //wait time to see byte package on scope
  return error;                       //return error code
}

//==============================================================================
uint8_t I2c_ReadByte (etI2cAck ack)
//==============================================================================
{
  uint8_t mask,rxByte=0;
  SDA_HIGH();                           //release SDA-line
  for (mask=0x80; mask>0; mask>>=1)   //shift bit for masking (8 times)
  { SCL_HIGH();                         //start clock on SCL-line
    DelayMicroSeconds(1);             //data set-up time (t_SU;DAT)
    DelayMicroSeconds(3);             //SCL high time (t_HIGH)
    if ( GPIO_ReadInputDataBit( SHT21_GPIO_PORT, SHT21_GPIO_SDA_PIN ) == Bit_SET ) rxByte=(rxByte | mask); //read bit
    SCL_LOW();
    DelayMicroSeconds(1);             //data hold time(t_HD;DAT)
  }

  if( ack == ACK )
	 SDA_LOW();
  else
	  SDA_HIGH();

  DelayMicroSeconds(1);               //data set-up time (t_SU;DAT)
  SCL_HIGH();                           //clk #9 for ack
  DelayMicroSeconds(5);               //SCL high time (t_HIGH)
  SCL_LOW();
  SDA_HIGH();                           //release SDA-line
  DelayMicroSeconds(20);              //wait time to see byte package on scope
  return rxByte;                      //return error code
}

